// TestXTuple.java

package com.ibm.tspaces.examples.xml;

/*
**  Licensed Materials - Property of IBM
**
**  (C) COPYRIGHT IBM Corp. 1996, 1997, 1998, 1999  All rights reserved
**
**  US Government Users Restricted Rights - Use, duplication or
**  disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
**
*/

import java.io.*;
import java.util.*;
import com.ibm.tspaces.*;
import com.ibm.tspaces.query.XMLQuery;

/*****************************************************************
 ** TestXSuite.java **
 *********************
 ** TestXSuite is the class I will use to test the correctness of
 ** my XTuple implementation.  It includes several testcases which
 ** are run automatically and report errors if they do not match
 ** the expected results.  To take away dependence on external 
 ** files, I've actually embedded the test.xml file inside the
 ** testcases as a constant.
 **
 ** @see XTuple
 ** @see TupleTree
 ** @author Ben Y. Zhao
 **/

public class TestXSuite implements Callback {

  /* Constructor */
  public TestXSuite() {

  }
  
  /* Members */

  static String _tsServerName = "localhost";
  /**
   ** The test XML document string
   **/
  static final String xml = "<?xml version=\"1.0\"?>"+
                            "<TEST>"+
                            "  <TAG1 x=\"y\">valueA</TAG1>"+
                            "  <TAG2 a=\"b\">valueB</TAG2>"+
                            "  <PARENT>"+
                            "    <CHILD>"+
                            "       <GRANDBABY age=\"0\">baby</GRANDBABY>"+
                            "       <GRANDBOY age=\"1\">boy</GRANDBOY>"+
                            "       <GRANDGIRL age=\"2\">girl</GRANDGIRL>"+
                            "       <GRANDGRANDCHILD age=\"3\">"+
                            "           <FIRSTNAME>Ben</FIRSTNAME>"+
                            "           <LASTNAME>Zhao</LASTNAME>"+
                            "       </GRANDGRANDCHILD>"+
                            "    </CHILD>"+
                            "  </PARENT>"+
                            "  <NEIGHBOR>"+
                            "    <LASTNAME>Flanders</LASTNAME>"+
                            "    <FIRSTNAME>Jim</FIRSTNAME>"+
                            "  </NEIGHBOR>"+
                            "</TEST>";
  
  static final String xml2 = "<?xml version=\"1.0\"?>"+
                            "<TEST>"+
                            "  <TAG1 x=\"y\">valueC</TAG1>"+                           
                            "  <PARENT>"+
                            "    <CHILD>"+
                            "           <FIRSTNAME>Norm</FIRSTNAME>"+
                            "           <LASTNAME>Pass</LASTNAME>"+
                            "    </CHILD>"+  
                            "  </PARENT>"+                            
                            "</TEST>";
  static final String xml3 = "<?xml version=\"1.0\"?>"+
                          "<invoicecollection>"+
                          "<invoice>"+
                          " <customer>"+
                          "      Wile E. Coyote, Death Valley, CA"+
                          " </customer>"+                          
                          " <annotation>"+
                          "  Customer asked that we guarantee return rights if these items"+
                          "  should fail in desert conditions. This was approved by Marty"+
                          "  Melliore, general manager."+
                          "  </annotation>"+
                          "   <entries n=\"2\">"+
                          "      <entry quantity=\"2\"  total_price=\"134.00\">"+
                          "         <product maker=\"ACME\" prod_name=\"screwdriver\" price=\"80.00\"/>"+
                          "      </entry>"+
                          "      <entry quantity=\"1\"  total_price=\"20.00\">"+
                          "         <product maker=\"ACME\" prod_name=\"power wrench\" price=\"20.00\"/>"+
                          "      </entry>"+
                          "   </entries>"+

                          " </invoice>"+
                          " <invoice>"+
                          "   <customer>"+
                          "        Camp Mertz"+
                          "   </customer>"+
                          "   <entries n=\"2\">"+
                          "      <entry quantity=\"2\"  total_price=\"32.00\">"+
                          "         <product maker=\"BSA\" prod_name=\"left-handed smoke shifter\" price=\"16.00\"/>"+
                          "      </entry>"+
                          "      <entry quantity=\"1\"  total_price=\"13.00\">"+
                          "         <product maker=\"BSA\" prod_name=\"snipe call\" price=\"13.00\"/>"+
                          "      </entry>"+
                          "   </entries>"+
                          " </invoice>"+
                          "</invoicecollection>";
  static final String xml4 = "<?xml version=\"1.0\"?>"+
                          "<testDelete>"+
                          "  <test> data </test>"+
                          "</testDelete>";
  
  boolean  _callbackOK = false;                          
                        
  public static void main(String [] argv) {
    if (argv.length == 1 && argv[0].equals("-D")) {
      Debug.setDebugOn(true);
    }
    TestXSuite txt = new TestXSuite();
    txt.run();
  }

  public void run() {
    String xql;
    Tuple result;
    int passed, failed;
    passed = failed = 0;
    try {
      TupleSpace ts = new TupleSpace("xmlTest", _tsServerName);
      Debug.out("XMLTest TSpace created.");
      
      ts.deleteAll();
      
      Debug.setAssert(true);  // Invoke Assert even if Debug.ON is false
      //TupleSpace.setDebug(true);
      TupleID tid1 = write(ts,xml);
      TupleID tid2 = write(ts,xml2);
      TupleID tid3 = write(ts,xml3);
      
      
      
  // insert special tests here 
    
      

  //System.exit(1); 
  
      Debug.out(0,"Test #0: Verify simple template match works");
      Tuple template = new Tuple("Test",new Field(String.class));
      result = ts.scan(template);
      if (result.numberOfFields() == 3) {
            passed++;
            Debug.out(0, "Passed.");
            //display(1,result);
      } else {
            Debug.out(0, "Failed.");
            display(0,result);
            failed++;
      }

      
      xql = "LASTNAME";      
      Debug.out(0, "Test #1: Simple match on tag name. "+"XQL: "+xql);
      result = ts.scan(new XMLQuery(xql));
      Debug.out(result);
      
      if (result.numberOfFields() == 2) {
            passed++;
            Debug.out(0,"Passed.");
            display(1,result);
      } else {
            Debug.out(0, "Failed.");
            display(0,result);
            failed++;
      }

  

  
      xql = "/TEST/TAG2='valueB'";
      Debug.out(0, "Test #2: Anchored match with tagvalue constraint. "+"XQL: "+xql);
      result = ts.scan(new XMLQuery(xql));
      
      
      if (result.numberOfFields() == 1) {
            Debug.out(0, "Passed.");
            display(1,result);
            passed++;
      } else {
            Debug.out(0, "Failed.");
            display(0,result);
            failed++;
      }

      xql = "PARENT/*/GRANDBOY='boy'";
      Debug.out(0, "Test #3: Wildcard in path expression with tagvalue. "+"XQL: "+xql);
      result = ts.scan(new XMLQuery(xql));
      
      
      if (result.numberOfFields() == 1) {
            Debug.out(0, "Passed.");
            display(1,result);
            passed++;
      } else {
            Debug.out(0, "Failed.");
            display(0,result);
            failed++;
      }

      xql = "/TEST//LASTNAME";
      Debug.out(0, "Test #4: Descendant test with anchored root tag. "+"XQL: "+xql);
      result = ts.scan(new XMLQuery(xql));
      
          
      if (result.numberOfFields() == 2) {
            Debug.out(0, "Passed.");
            display(1,result);
            passed++;
      } else {
            Debug.out(0, "Failed.");
            failed++;            
            display(0,result);
      }

      xql = "GRANDGRANDCHILD[@age='3']/LASTNAME='Zhao'";
      Debug.out(0, "Test #5: parent attributes and child tagvalue. "+"XQL: "+xql);
      result = ts.scan(new XMLQuery(xql));
      
      
      if (result.numberOfFields() == 1) {
            Debug.out(0, "Passed.");
            display(1,result);
            passed++;
      } else {
            Debug.out(0, "Failed.");
            display(0,result);
            failed++;
      }

      xql = "/TEST/NEIGHBOR/FIRSTNAME='Bob'";
      Debug.out(0, "Test #6: invalid tagvalue. "+"XQL: "+xql);
      result = ts.scan(new XMLQuery(xql));
      

      if (result.numberOfFields() == 0) {
            Debug.out(0, "Passed.");
            display(1,result);
            passed++;
      } else {
            Debug.out(0, "Failed.");
            display(0,result);
            failed++;
      }

      xql = "CHILD/GRANDBABY[@age='5']";
      Debug.out(0, "Test #7: invalid attribute value. "+"XQL: "+xql);
      result = ts.scan(new XMLQuery(xql));
      
      
      if (result.numberOfFields() == 0) {
            Debug.out(0, "Passed.");
            passed++;
      } else {
            Debug.out(0, "Failed.");
            display(1,result);
            failed++;
      }

      xql = "invoice//product";
      Debug.out(0, "Test #8: Standard decendant path. "+"XQL: "+xql);
      result = ts.scan(new XMLQuery(xql));
      
      
      if (result.numberOfFields() == 1) {
            Debug.out(0, "Passed.");
            display(1,result);
            passed++;
      } else {
            Debug.out(0, "Failed.");
            display(0,result);
            failed++;
      }
      
      Debug.out(0, "Test #9: Test ability to delete XML tuples");
      int origcount = ts.countN(new Tuple());
      int origcountx = ts.countN(new XMLTuple());
      Debug.out("Original count = "+origcount+";"+origcountx);
      
      TupleID tid4a = write(ts,xml4);
      TupleID tid4b = writeBytes(ts,xml4);
      int newcount = ts.countN(new Tuple());
      int newcountx = ts.countN(new XMLTuple());
      Debug.out("New count = "+newcount+";"+newcountx);
      ts.deleteTupleById(tid4a);
      result = ts.take(new XMLQuery("/testDelete"));
      int finalcount = ts.countN(new Tuple());
      int finalcountx = ts.countN(new XMLTuple());
      Debug.out("Final count = "+finalcount+";"+finalcountx);

      // verify that we added stuff and then deleted the stuff
      if (newcount > origcount && finalcount == origcount && 
          newcountx > origcountx && finalcountx == origcountx) {
            Debug.out(0, "Passed.");
            display(1,result);
            passed++;
      } else {
            Debug.out(0, "Failed.");
            display(0,result);
            failed++;
      }
      
      
      xql = "invoice//product";
      Debug.out(0, "Test #10: Event Register with XQLQuery. "+"XQL: "+xql);
      Tuple query = new Tuple(new XMLQuery(xql));
      int seq  = ts.eventRegister(TupleSpace.WRITE,query,this);
      
      write(ts,xml3);
      result = ts.scan(query);
      if (_callbackOK) {
        Debug.out(0, "Passed.");
        
        passed++;
      } else {
        Debug.out(0, "Failed.");
        Debug.out(0, "Callback should have recieved: "+result);
        failed++;
      }

      
      
      
      Debug.out(0,""+ (passed+failed) +" Tests: "+passed+" passed, "+failed+" failed.");
    } catch (Exception e) {
      Debug.out(0, e);
    }
  }
  
  public boolean call(String eventName,String tsName,int seqNum,SuperTuple tuple,boolean isException)   {
        if (! isException) { 
          Debug.out("call: "+tuple);
          _callbackOK = true;
        } else {
          Debug.out(0,tuple); 
        }
        return false;  
      } // call()
  

  
  private void display(int n, Tuple result) {
    try { 
      if (result == null) {
        Debug.out(n,"Result: null"); 
        return;
      }
      if (result.numberOfFields() == 0) {
        Debug.out(n,"Result: null Tuple");
        return;
      }
      for(int i=0; i<result.numberOfFields();i++) {
        Debug.out(n,"Result "+i+": "+result.getField(i));
      }
    } catch (Exception e) {
      Debug.out(e);
    }
  }
  
  
  private TupleID write(TupleSpace ts, String xml) {   
    try { 
      Field xmlF = new XMLField(xml);      
      Tuple xmlT = new Tuple("Test",xmlF);
      Debug.out("XMLTest tuple created.");
      TupleID tid = ts.write(xmlT);
      Debug.out("XMLTest tuple written.");
      SuperTuple wrote = ts.readTupleById(tid);
      Debug.out(tid+":"+wrote);
      return tid;
    } catch (Exception e) {
      Debug.out(e);
      return null;
    }
  }
  // write Tuple using byte array
   private TupleID writeBytes(TupleSpace ts, String xml) {   
    try { 
      byte[] bytes =xml.getBytes();
      Field xmlF = new XMLField(bytes);      
      Tuple xmlT = new Tuple("Test");
      xmlT.add(xmlF);
      Debug.out("XMLTest tuple created.");
      TupleID tid = ts.write(xmlT);
      Debug.out("XMLTest tuple written.");
      SuperTuple wrote = ts.readTupleById(tid);
      Debug.out(tid+":"+wrote);
      return tid;
    } catch (Exception e) {
      Debug.out(e);
      return null;
    }
  }
}

/* $Log: TestXSuite.java,v $
/* Revision 2.1.2.3  2000/10/18 12:44:46  jthomas
/* no message
/*
/* Revision 2.1.2.2  2000/08/30 13:04:23  jthomas
/* add new debug msg
/*
/* Revision 2.1.2.1  2000/02/22 23:54:54  jthomas
/* Improve tests to cover problems found in 2.1.1
/*
/* Revision 2.1  1999/11/05 22:22:41  estesp
/* Update revision number to 2.1 on all files
/*
/* Revision 1.1.1.1  1999/11/05 16:24:54  estesp
/* Imported 2.1.0 release into Austin CVS
/*
 * Revision 1.6  1999/10/27 19:19:13  jthomas
 * Improve the delete tuple test
 *
 * Revision 1.5  1999/10/26 18:44:39  jthomas
 * Add a new test of the delete ability.
 *
 * Revision 1.4  1999/10/22 20:18:46  jthomas
 * Improved the TestSuite to add a few more tests
 *
 * Revision 1.3  1999/10/22 14:09:59  jthomas
 * Updated for new XML changes
 *
 * Revision 1.2  1999/09/12 15:08:48  jthomas
 * Fix tabs and add some debug messages
 *
 * Revision 1.1  1999/09/12 12:22:07  jthomas
 * Move xml tests to examples directory
 *
 * Revision 1.1  1999/09/10 17:11:29  ravenben
 * modified some code an added the XQL test suite
 *
 */